#include "AudioInputSamp.h"
#include "ui_AudioInputSamp.h"
#include <QChart>
#include <QValueAxis>
#include <QAudio>
#include <QMessageBox>
#include <QAudioRecorder>

AudioInputSamp::AudioInputSamp(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::AudioInputSamp)
{
    ui->setupUi(this);

    //创建显示图表
    QChart *chart = new QChart;
    chart->setTitle ("音频输入原始信号") ;
    ui->widget_chartView->setChart(chart);
    m_lineSeries= new QLineSeries(); //序列
    chart->addSeries (m_lineSeries) ;

    QValueAxis *axisX = new QValueAxis; //坐标轴
    axisX->setRange (0, m_displayPointsCount); //chart 显示4000个采样点数据
    axisX->setLabelFormat ("%g") ;
    axisX->setTitleText ("Samples") ;
    QValueAxis *axisY = new QValueAxis; //坐标轴
    axisY->setRange(0, 256); // UnSingedInt 采样，数据范围0-255
    axisY->setTitleText ("Audio level") ;

    //! 最新方法设置轴
    //设置X在下面，Y在zuo左边
    chart->addAxis(axisX, Qt::AlignBottom) ;
    chart->addAxis(axisY, Qt::AlignLeft) ;
    m_lineSeries->attachAxis(axisX);
    m_lineSeries->attachAxis(axisY);
    //! 下面两个方法是过时方法，同上面四行代码效果，目前一样可用
//    chart->setAxisX(axisX, m_lineSeries);
//    chart->setAxisY(axisY, m_lineSeries);

    chart->legend()->hide() ;
    ui->comboDevices->clear() ;

    m_DeviceList =QAudioDeviceInfo::availableDevices (QAudio::AudioInput);

    for(int i=0; i<m_DeviceList.count() ;i++){
        QAudioDeviceInfo device=m_DeviceList.at (i) ;
        ui ->comboDevices->addItem (device. deviceName () ) ;
    }

    if (m_DeviceList.size()>0){
        ui -> comboDevices->setCurrentIndex (0) ;
        m_currentDevice =m_DeviceList.at(0);
    }
    else{
        ui->actStart->setEnabled(false) ;
        ui ->actDeviceTest->setEnabled(false) ;
        ui->groupBoxDevice->setTitle("支持的音频输入设置(无设备)") ;
    }
}

AudioInputSamp::~AudioInputSamp()
{
    delete ui;
}

void AudioInputSamp::onIODeviceUpdateBlockSize(qint64 blockSize)
{
    //显示缓冲区大小和数据块大小
    ui->LabBufferSize->setText(QString::asprintf("QAudioInput::bufferSize () =%d" , m_AudioInput->bufferSize())) ;
    ui->LabBufferSize->setText(ui->LabBufferSize->text() +"\t"+QString("IODevice数据块字节数=%1") .arg (blockSize));
}


void AudioInputSamp::on_comboDevices_currentIndexChanged(int index)
{
    //!通过UI设计器右键跳转 comboDevices 组件 currentIndexChanged( int index ) 信号来关联的信号槽
    //选择音频输入设备
    m_currentDevice =m_DeviceList.at(index);//当前音频设备
    ui ->comboCodec->clear(); //支持的 音频编码

    QStringList codecs = m_currentDevice.supportedCodecs() ;
    for (int i = 0; i < codecs.size() ; ++i){
        ui->comboCodec->addItem(codecs.at(i));
    }

    ui->comboSampleRate->clear(); // 支持的采样率
    QList<int> sampleRate = m_currentDevice.supportedSampleRates ();
    for (int i = 0; i < sampleRate.size() ; ++i){
        ui->comboSampleRate->addItem(QString ("%1") .arg (sampleRate.at(i))) ;
    }

    ui->comboChannels->clear() ;//支持的通道数
    QList<int> Channels = m_currentDevice.supportedChannelCounts();
    for (int i = 0; i < Channels.size() ; ++i){
        ui-> comboChannels->addItem (QString ("%1") .arg (Channels.at(i)));
    }

    ui->comboSampleTypes->clear(); //支持的采样点类型
    QList<QAudioFormat::SampleType> sampleTypes = m_currentDevice.supportedSampleTypes() ;
    for (int i = 0; i < sampleTypes.size() ; ++i){
        ui ->comboSampleTypes->addItem(SampleTypeString (sampleTypes.at(i)),QVariant (sampleTypes.at(i))) ;
    }

    ui->comboSampleSizes->clear() ;//采样点大小.
    QList<int> sampleSizes = m_currentDevice.supportedSampleSizes() ;
    for (int i = 0; i < sampleSizes.size() ; ++i){
        ui->comboSampleSizes->addItem (QString("%1") .arg(sampleSizes.at(i))) ;
    }

    ui->comboByteOrder->clear();//字节序
    QList<QAudioFormat::Endian> endians = m_currentDevice.supportedByteOrders () ;
    for (int i = 0; i < endians.size() ; ++i){
        ui->comboByteOrder->addItem(ByteOrderString(endians.at (i) )) ;
    }

}

QString AudioInputSamp::SampleTypeString(QAudioFormat::SampleType sampleType)
{
    //将QAudioFormat: :SampleType类型转换为字符串
    QString result ("Unknown") ;
    switch (sampleType) {
    case QAudioFormat::SignedInt:
        result = "SignedInt";
        break;
    case QAudioFormat::UnSignedInt:
        result = "UnSignedInt";
        break;
    case QAudioFormat::Float:
        result = "Float";
        break;
    case QAudioFormat::Unknown:
        result = "Unknown";
        break;
    }

    return result;
}

QString AudioInputSamp::ByteOrderString(QAudioFormat::Endian endian)
{
    //将QAudioFormat: :Endian转换为字符串
    if (endian==QAudioFormat::LittleEndian){
        return "LittleEndian";
    }
    else if (endian==QAudioFormat::BigEndian)
    {
        return "BigEndian";
    }
    else{
        return "Unknown";
    }

}

void AudioInputSamp::on_actDeviceTest_clicked()
{
    //测试音频输入设备是否支持选择的设置
    QAudioFormat settings;
    settings.setCodec (ui->comboCodec->currentText()) ;
    settings.setSampleRate (ui->comboSampleRate->currentText().toInt() ) ;
    settings.setChannelCount (ui->comboChannels->currentText().toInt()) ;
    settings.setSampleType(QAudioFormat::SampleType (ui->comboSampleTypes->currentData() . toInt()));
    settings.setSampleSize (ui->comboSampleSizes->currentText().toInt()) ;

    if (ui->comboByteOrder ->currentText ()=="LittleEndian"){
        settings.setByteOrder(QAudioFormat::LittleEndian) ;
    }
    else{
        settings.setByteOrder(QAudioFormat::BigEndian) ;
    }

    if (m_currentDevice.isFormatSupported (settings)){
        QMessageBox::information(this, "音频测试", "测试成功，输入设备支持此设置.");
    }
    else{
        QMessageBox::critical (this, "音频测试", "测试失败，输入设备不支持此设置.");
    }

}

void AudioInputSamp::on_actStart_clicked()
{
    //开始音频输入
    QAudioFormat defaultAudioFormat;  //缺省格式
    defaultAudioFormat.setSampleRate (8000) ;
    defaultAudioFormat.setChannelCount (1) ;
    defaultAudioFormat.setSampleSize(8) ;
    defaultAudioFormat.setCodec ("audio/pcm") ;
    defaultAudioFormat.setByteOrder(QAudioFormat::LittleEndian) ;
    defaultAudioFormat. setSampleType (QAudioFormat::UnSignedInt) ;
    if (!m_currentDevice.isFormatSupported (defaultAudioFormat)){

        QMessageBox::critical (this, "测试", "测试失败，输入设备不支持此设置.") ;
        return;
    }

    m_AudioInput = new QAudioInput (m_currentDevice, defaultAudioFormat, this) ;
    m_AudioInput->setBufferSize(m_displayPointsCount) ;

    //接收音频输入数据的流设备
    m_mineDisplayDevice = new MineDisplayDevice (m_lineSeries, m_displayPointsCount, this) ;

    connect (m_mineDisplayDevice , SIGNAL (updateBlockSize (qint64)) ,this, SLOT (onIODeviceUpdateBlockSize(qint64)));

    m_mineDisplayDevice->open(QIODevice::WriteOnly) ;
    m_AudioInput->start(m_mineDisplayDevice) ;
    ui->actStart->setEnabled(false) ;
    ui ->actStop->setEnabled(true) ;
}

void AudioInputSamp::on_actStop_clicked()
{
    m_mineDisplayDevice->close();
    m_AudioInput->stop();
    ui->actStart->setEnabled(true) ;
    ui ->actStop->setEnabled(false) ;
}
